#deep seek编写
import fitz  # PyMuPDF
import pytesseract
from PIL import Image
import io
import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import webbrowser
from packaging import version

class PDFOCRApp:
    def __init__(self, root):
        self.root = root
        self.root.title("PDF扫描件文字识别工具 v2.0")
        self.root.geometry("650x450")
        
        # 初始化Tesseract状态
        self.tesseract_installed = False
        self.tesseract_version = None
        
        # 检查Tesseract安装
        self.check_tesseract()
        
        # 如果Tesseract未安装，显示安装提示
        if not self.tesseract_installed:
            self.show_install_prompt()
            return
        
        # 创建界面元素
        self.create_widgets()
        
    def check_tesseract(self):
        """检查Tesseract OCR是否安装"""
        try:
            # 尝试获取Tesseract路径
            try:
                tesseract_path = pytesseract.pytesseract.tesseract_cmd
            except:
                tesseract_path = None
                
            if not tesseract_path or not os.path.isfile(tesseract_path):
                # 如果在默认路径找不到，尝试自动查找
                possible_paths = [
                    r'C:\Program Files\Tesseract-OCR\tesseract.exe',
                    r'C:\Program Files (x86)\Tesseract-OCR\tesseract.exe',
                    '/usr/local/bin/tesseract',
                    '/usr/bin/tesseract',
                    '/opt/homebrew/bin/tesseract'
                ]
                
                for path in possible_paths:
                    if os.path.isfile(path):
                        pytesseract.pytesseract.tesseract_cmd = path
                        tesseract_path = path
                        break
                else:
                    self.tesseract_installed = False
                    return
            
            # 获取版本信息 - 新方法
            try:
                # 直接运行tesseract --version命令获取原始版本字符串
                version_output = pytesseract.get_tesseract_version()
                
                # 处理不同格式的版本输出
                if isinstance(version_output, (list, tuple)):  # 某些版本返回列表
                    version_str = version_output[0]
                else:  # 其他情况直接使用字符串
                    version_str = str(version_output)
                
                # 从字符串中提取版本号 (例如从 "tesseract 4.1.1" 中提取 "4.1.1")
                import re
                version_match = re.search(r'\d+\.\d+(\.\d+)?', version_str)
                if version_match:
                    version_str = version_match.group(0)
                    self.tesseract_version = version_str
                    self.tesseract_installed = True
                    print(f"检测到Tesseract版本: {version_str}")
                else:
                    print(f"无法解析版本信息: {version_str}")
                    self.tesseract_installed = True  # 仍视为已安装，只是版本未知
                    self.tesseract_version = "未知版本"
                    
            except Exception as e:
                print(f"获取Tesseract版本时出错: {e}")
                # 如果能找到tesseract但无法获取版本，仍视为已安装
                self.tesseract_installed = True
                self.tesseract_version = "版本检测失败"
                
        except Exception as e:
            print(f"检查Tesseract时出错: {e}")
            self.tesseract_installed = False
    
    def show_install_prompt(self):
        """显示Tesseract安装提示"""
        self.root.geometry("500x300")
        
        tk.Label(self.root, text="Tesseract OCR未安装", font=("Arial", 16, "bold"), 
                fg="red").pack(pady=20)
        
        tk.Label(self.root, text="本程序需要Tesseract OCR引擎才能运行", 
                font=("Arial", 12)).pack(pady=10)
        
        tk.Label(self.root, text="请安装Tesseract OCR并添加中文语言包", 
                font=("Arial", 12)).pack(pady=10)
        
        # 下载按钮
        download_frame = tk.Frame(self.root)
        download_frame.pack(pady=20)
        
        tk.Button(download_frame, text="Windows版下载", command=lambda: webbrowser.open(
            "https://github.com/UB-Mannheim/tesseract/wiki")).pack(side=tk.LEFT, padx=10)
        
        tk.Button(download_frame, text="macOS安装指南", command=lambda: webbrowser.open(
            "https://formulae.brew.sh/formula/tesseract")).pack(side=tk.LEFT, padx=10)
        
        tk.Button(download_frame, text="Linux安装指南", command=lambda: webbrowser.open(
            "https://tesseract-ocr.github.io/tessdoc/Installation.html")).pack(side=tk.LEFT, padx=10)
        
        # 检查按钮
        tk.Button(self.root, text="我已安装，重新检查", command=self.recheck_tesseract,
                 bg="#4CAF50", fg="white").pack(pady=20)
        
        # 退出按钮
        tk.Button(self.root, text="退出程序", command=self.root.quit,
                 bg="#f44336", fg="white").pack(pady=10)
    
    def recheck_tesseract(self):
        """重新检查Tesseract安装"""
        self.check_tesseract()
        if self.tesseract_installed:
            # 清除当前窗口内容
            for widget in self.root.winfo_children():
                widget.destroy()
            # 重新创建主界面
            self.root.geometry("650x450")
            self.create_widgets()
            messagebox.showinfo("成功", f"Tesseract OCR {self.tesseract_version} 已检测到!")
        else:
            messagebox.showerror("错误", "仍未检测到Tesseract OCR，请确保已正确安装")
    
    def create_widgets(self):
        """创建主界面控件"""
        # 输入PDF文件选择
        tk.Label(self.root, text="输入PDF文件:").grid(row=0, column=0, padx=5, pady=5, sticky="e")
        self.input_path = tk.StringVar()
        tk.Entry(self.root, textvariable=self.input_path, width=50).grid(row=0, column=1, padx=5, pady=5)
        tk.Button(self.root, text="浏览...", command=self.browse_input).grid(row=0, column=2, padx=5, pady=5)
        
        # 输出目录选择
        tk.Label(self.root, text="输出目录:").grid(row=1, column=0, padx=5, pady=5, sticky="e")
        self.output_dir = tk.StringVar()
        tk.Entry(self.root, textvariable=self.output_dir, width=50).grid(row=1, column=1, padx=5, pady=5)
        tk.Button(self.root, text="浏览...", command=self.browse_output).grid(row=1, column=2, padx=5, pady=5)
        
        # 输出文件名
        tk.Label(self.root, text="输出文件名:").grid(row=2, column=0, padx=5, pady=5, sticky="e")
        self.output_name = tk.StringVar()
        tk.Entry(self.root, textvariable=self.output_name, width=50).grid(row=2, column=1, padx=5, pady=5)
        
        # 输出格式选择
        tk.Label(self.root, text="输出格式:").grid(row=3, column=0, padx=5, pady=5, sticky="e")
        self.output_format = tk.StringVar(value="txt")
        ttk.Combobox(self.root, textvariable=self.output_format, 
                     values=("txt", "docx", "csv", "json"), width=47).grid(row=3, column=1, padx=5, pady=5)
        
        # DPI设置
        tk.Label(self.root, text="扫描质量(DPI):").grid(row=4, column=0, padx=5, pady=5, sticky="e")
        self.dpi = tk.IntVar(value=300)
        ttk.Combobox(self.root, textvariable=self.dpi, 
                     values=(200, 300, 400, 500, 600), width=47).grid(row=4, column=1, padx=5, pady=5)
        
        # 语言选择
        tk.Label(self.root, text="OCR语言:").grid(row=5, column=0, padx=5, pady=5, sticky="e")
        self.language = tk.StringVar(value="chi_sim+eng")
        ttk.Combobox(self.root, textvariable=self.language, 
                     values=("chi_sim", "eng", "chi_sim+eng", "chi_tra", "chi_tra+eng"), 
                     width=47).grid(row=5, column=1, padx=5, pady=5)
        
        # 显示Tesseract信息
        tesseract_info = f"Tesseract OCR {self.tesseract_version} (已安装)"
        tk.Label(self.root, text=tesseract_info, fg="green").grid(row=6, column=1, sticky="w", pady=5)
        
        # 进度条
        self.progress = ttk.Progressbar(self.root, orient="horizontal", length=450, mode="determinate")
        self.progress.grid(row=7, column=0, columnspan=3, pady=10)
        
        # 处理按钮
        tk.Button(self.root, text="开始转换", command=self.process_pdf, 
                 bg="#4CAF50", fg="white", font=("Arial", 10, "bold")).grid(row=8, column=1, pady=10)
        
        # 状态栏
        self.status = tk.StringVar(value="准备就绪")
        tk.Label(self.root, textvariable=self.status, bd=1, relief=tk.SUNKEN, anchor=tk.W).grid(
            row=9, column=0, columnspan=3, sticky="we")
    
    def browse_input(self):
        filename = filedialog.askopenfilename(
            title="选择PDF文件",
            filetypes=(("PDF文件", "*.pdf"), ("所有文件", "*.*")))
        if filename:
            self.input_path.set(filename)
            # 自动设置输出文件名
            base_name = os.path.splitext(os.path.basename(filename))[0]
            self.output_name.set(base_name + "_OCR")
            # 自动设置输出目录为输入文件所在目录
            self.output_dir.set(os.path.dirname(filename))
    
    def browse_output(self):
        directory = filedialog.askdirectory(title="选择输出目录")
        if directory:
            self.output_dir.set(directory)
    
    def update_progress(self, value):
        self.progress["value"] = value
        self.root.update_idletasks()
    
    def process_pdf(self):
        input_pdf = self.input_path.get()
        output_dir = self.output_dir.get() or os.path.dirname(input_pdf)
        output_name = self.output_name.get() or "output"
        output_format = self.output_format.get()
        dpi = self.dpi.get()
        language = self.language.get()
        
        if not input_pdf:
            messagebox.showerror("错误", "请选择输入PDF文件")
            return
        
        if not os.path.exists(input_pdf):
            messagebox.showerror("错误", "输入的PDF文件不存在")
            return
        
        # 检查语言包是否安装
        try:
            pytesseract.get_languages(config='')
        except Exception as e:
            if "chi_sim" in language and "Error opening data file" in str(e):
                messagebox.showerror("语言包缺失", 
                    "中文语言包未安装\n\n"
                    "Windows用户: 请重新运行Tesseract安装程序并勾选中文语言包\n"
                    "macOS用户: 运行 'brew install tesseract-lang'")
                return
        
        try:
            self.status.set("正在处理...")
            self.update_progress(0)
            
            # 打开PDF文件
            doc = fitz.open(input_pdf)
            total_pages = len(doc)
            text_content = []
            
            for page_num in range(total_pages):
                page = doc.load_page(page_num)
                
                # 更新进度
                progress = (page_num + 1) / total_pages * 100
                self.update_progress(progress)
                self.status.set(f"正在处理第 {page_num + 1}/{total_pages} 页...")
                
                # 将PDF页面转换为图像
                pix = page.get_pixmap(dpi=dpi)
                img_bytes = pix.tobytes("ppm")
                img = Image.open(io.BytesIO(img_bytes))
                
                # 使用Tesseract进行OCR识别
                text = pytesseract.image_to_string(img, lang=language)
                text_content.append(text)
            
            doc.close()
            
            full_text = "\n".join(text_content)
            
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            # 确定输出路径
            output_path = os.path.join(output_dir, f"{output_name}.{output_format}")
            
            # 根据格式保存
            if output_format == "txt":
                with open(output_path, "w", encoding="utf-8") as f:
                    f.write(full_text)
            elif output_format == "docx":
                from docx import Document
                doc = Document()
                doc.add_paragraph(full_text)
                doc.save(output_path)
            elif output_format == "csv":
                import csv
                with open(output_path, "w", newline="", encoding="utf-8") as f:
                    writer = csv.writer(f)
                    for line in full_text.split("\n"):
                        writer.writerow([line])
            elif output_format == "json":
                import json
                data = {"pages": text_content}
                with open(output_path, "w", encoding="utf-8") as f:
                    json.dump(data, f, ensure_ascii=False, indent=2)
            
            self.update_progress(100)
            self.status.set(f"处理完成! 结果已保存到: {output_path}")
            messagebox.showinfo("完成", f"PDF转换完成!\n结果已保存到:\n{output_path}")
            
        except Exception as e:
            self.status.set("处理出错")
            messagebox.showerror("错误", f"处理过程中发生错误:\n{str(e)}")
        finally:
            self.update_progress(0)

if __name__ == "__main__":
    # 检查必要库是否安装
    try:
        import pytesseract
        import fitz
        from packaging import version
    except ImportError as e:
        print(f"缺少必要依赖: {e}")
        print("请运行: pip install pymupdf pytesseract pillow python-docx packaging")
        input("按Enter键退出...")
        sys.exit(1)
    
    root = tk.Tk()
    app = PDFOCRApp(root)
    root.mainloop()